function Html_Pages(gui, user, date, options, message) {
  this._gui = gui;
  this._user = user;
  this._date = date;
  this._options = options;
  this._message = message;

  this._createElements();
};

Html_Pages.prototype._createElements = function() {
  // Data
  this._root = (this._message['m']) ? this._message['m'] : null;
  this._source = null;
  this._target = null;

  // Display
  var tmpRoot = MiscUtils.clone(this._root);
  this._createTable(tmpRoot, this._gui.content);

  // Event
  this._gui.add.onclick = function() {
  }
};

Html_Pages.prototype._getAncestorNumArr = function(haystack, needle, ancNumArr) {
  if (haystack.id == needle.id) {
    return true;
  }
  for ( var i = 0, il = haystack.c.length; i < il; i++) {
    ancNumArr.push(i + 1);
    if (this._getAncestorNumArr(haystack.c[i], needle, ancNumArr)) {
      return true;
    }
    ancNumArr.pop();
  }
  return false;
};

Html_Pages.prototype._update = function(elmX, moveX, rowIdx) {
  var WIDTH = 25, OFFSET = 32, table, tr, td, div1, div2, pos, _self = this;

  this._target = this._iRows[rowIdx]._node;
  for ( var i = 0, il = this._iRows.length; i < il; i++) {
    var tmp = this._iRows[i];
    tmp.style.visibility = 'collapse';
  }
  this._iRows[rowIdx].style.visibility = 'visible';

  table = document.createElement('table');
  table.cellSpacing = 0;
  table.cellPadding = 0;
  tr = table.insertRow(-1);
  td = tr.insertCell(-1);
  td.style.height = '20px';
  td.style.width = +OFFSET + 'px';
  
  tr.onmousemove = function() {
    var evt = DOMUtils.getEvent();
    _self._update.call(_self, elmX, evt.clientX, rowIdx);
  };

  DOMUtils.removeChildElements(this._iRows[rowIdx].cells[0]);
  this._iRows[rowIdx].cells[0].appendChild(table);

  var opts = this._getOptions(this._source, this._iRows[rowIdx]._node);
  opts.sort(function(a, b) {
    return PIDTreeUtils.getFamily(a, _self._source).ancestors.length - PIDTreeUtils.getFamily(b, _self._source).ancestors.length;
  });
  for ( var i = 0, il = opts.length; i < il; i++) {
    var tmp = opts[i];
    td = tr.insertCell(-1);
    td.style.backgroundColor = '#eeeeee';
    td.style.borderLeft = '5px solid #adfadf';
    td.style.height = '20px';
    td.style.width = WIDTH + 'px';
    var pos = DOMUtils.findPos(td);
    if ((moveX < pos[0] && i == 0) || (moveX > pos[0] + WIDTH && i == il - 1) || (moveX >= pos[0] && moveX <= pos[0] + WIDTH)) {
      td.style.backgroundColor = '#ffff00';
      div2 = document.createElement('div');
      div2.style.backgroundColor = '#e8f08a'
      div2.style.padding = '20px 0 20px 32px';
      div2.style.border = 'thick solid #ffff00';
      div2.style.color = '#000000';
      div2.style.fontWeight = 'bold';

      var arr = [];
      this._getAncestorNumArr(tmp, this._source, arr);
      this._displayNode(this._source, div2, arr);

      this._iRows[rowIdx].cells[0].appendChild(div2);
    }
  }
  td = tr.insertCell(-1);
  td.style.borderLeft = '5px solid #adfadf';
};
Html_Pages.prototype._makeChanges = function() {
  //  var opts = this._getOptions(this._source, this._iSelected._node);
  //  this._displayOptions(opts);
  //
  this._source = null;
  this._createTable(MiscUtils.clone(this._root), this._gui.content);
};

/**
 * Conditions: a: has children, b: has parents (excl. ROOT), c: is the last child, d: is ROOT
 * Solutions: i: become sibling below the target, ii: become (the first) child of the target, iii: become sibling of the target's parent
 * Logics: 
 * 1. If target d, then ii
 * 2. If target !d,
 *   2-1 If target a, then ii
 *   2-2 If target !a,
 *     2-2-1 If target b, 
 *       2-2-1-1 If target c, i, ii, iii (target's parent become target and check if !d && b && c, then iii)
 *       2-2-1-2 If target !c, i, ii
 *     2-2-2 If target !b, then i, ii
 */
Html_Pages.prototype._getOptions = function(source, target) {
  var opts = [];
  if (target.id == 0) {
    opts[opts.length] = this._toFirstChild(source, target);
  } else {
    if (target.c.length > 0) {
      opts[opts.length] = this._toFirstChild(source, target);
    } else {
      var family = PIDTreeUtils.getFamily(this._root, target);
      if (family.ancestors.length > 0) {
        var parent = family.ancestors[family.ancestors.length - 1];
        if (parent.c[parent.c.length - 1].id == target.id) {
          var parentFamily = PIDTreeUtils.getFamily(this._root, parent);
          opts[opts.length] = this._toSibling(source, target, family);
          opts[opts.length] = this._toFirstChild(source, target);
          opts[opts.length] = this._toSibling(source, parent, parentFamily);

          this._goParent(source, parent, parentFamily, opts);
        } else {
          opts[opts.length] = this._toSibling(source, target, family);
          opts[opts.length] = this._toFirstChild(source, target);
        }
      } else {
        opts[opts.length] = this._toSibling(source, target, family);
        opts[opts.length] = this._toFirstChild(source, target);
      }
    }
  }
  return opts;
};

Html_Pages.prototype._goParent = function(source, target, family, opts) {
  var parent = family.ancestors[family.ancestors.length - 1];
  if (target.id != 0 && parent && parent.c[parent.c.length - 1].id == target.id) {
    var parentFamily = PIDTreeUtils.getFamily(this._root, parent);
    opts[opts.length] = this._toSibling(source, parent, parentFamily);
    this._goParent(source, parent, parentFamily, opts);
  }
};

Html_Pages.prototype._toSibling = function(source, target, family) {
  var tmpRoot = MiscUtils.clone(this._root);
  var tmpSource = PIDTreeUtils.findById(tmpRoot, source.id);
  tmpSource.parent_id = target.parent_id;
  tmpSource.order = (family.youngerBro) ? parseFloat(target.order, 10) + ((family.youngerBro.order - target.order) / 2) : parseFloat(target.order, 10) + 1;
  PIDTreeUtils.update(tmpRoot);
  return tmpRoot;
};

Html_Pages.prototype._toFirstChild = function(source, target, family) {
  var tmpRoot = MiscUtils.clone(this._root);
  var tmpSource = PIDTreeUtils.findById(tmpRoot, source.id);
  tmpSource.parent_id = target.id;
  tmpSource.order = (target.c.length > 0) ? target.c[0].order - 1 : source.order;
  PIDTreeUtils.update(tmpRoot);
  return tmpRoot;
};

Html_Pages.prototype._createTable = function(node, table) {
  var _self = this;

  DOMUtils.removeTableRows(table, 1);

  this._iRoot = node;
  this._iCount = 0;
  this._iRows = [];

  table.style.display = 'none';
  if (this._source) {
    var target = table.insertRow(-1);
    target.style.visibility = 'collapse';
    target.style.cursor = 'pointer';
    target._node = node;
    td = target.insertCell(-1);
    td.colSpan = 5;
    td.style.height = '20px';
    td.style.backgroundColor = '#52e5ba';
    this._iRows[this._iRows.length] = target;

    document.body.onmouseup = function() {
      if (_self._source) {
        _self._makeChanges.call(_self);
      }
    };
  }

  for ( var i = 0, il = node.c.length; i < il; i++) {
    var tmp = node.c[i];
    this._createTableRow(tmp, table, [ i + 1 ]);
  }
  table.style.display = 'table';

};

Html_Pages.prototype._createTableRow = function(node, table, ancNumArr) {
  var mBtn, rowIdx, tr, td, elm, _self = this;
  this._iCount++;

  tr = table.insertRow(-1);
  tr.style.height = '30px';
  tr.style.cursor = (this._source) ? 'move' : 'normal';
  if (this._source) {
    var target = table.insertRow(-1);
    target.style.visibility = 'collapse';
    target.style.cursor = 'pointer';
    target._node = node;
    td = target.insertCell(-1);
    td.colSpan = 5;
    td.style.height = '20px';
    td.style.backgroundColor = '#52e5ba';
    this._iRows[this._iRows.length] = target;

    rowIdx = this._iRows.length - 2;
    tr.onmouseover = function() {
      evt = DOMUtils.getEvent();
      _self._update.call(_self, DOMUtils.findPos(mBtn)[0], evt.clientX, rowIdx);
    };
    tr.onmousemove = function() {
      evt = DOMUtils.getEvent();
      _self._update.call(_self, DOMUtils.findPos(mBtn)[0], evt.clientX, rowIdx);
    };
  }

  tr.style.backgroundColor = (this._iCount % 2 == 0) ? '#eeeeee' : '#cccccc';

  td = tr.insertCell(-1);
  elm = document.createElement('input');
  elm.type = 'checkbox';
  td.appendChild(elm);

  td = tr.insertCell(-1);
  td.style.paddingLeft = '10px';
  this._setAncestorNum(td, ancNumArr, 0);
  if (node.type == Constant.PAGE_TYPE_COMMON) {
    elm = document.createElement('a');
    elm.href = 'admin.php?b=baseblank&t=page&i=' + node.id;
    elm.appendChild(document.createTextNode(node.name));
    td.appendChild(elm);
  } else {
    td.appendChild(document.createTextNode(node.name));
  }

  elm = document.createElement('img');
  elm.src = 'image/edit.png';
  elm.style.marginLeft = '10px';
  elm.style.cursor = 'pointer';
  elm.onclick = function() {
  };
  td.appendChild(elm);

  mBtn = document.createElement('img');
  mBtn.src = 'image/move.png';
  mBtn.style.marginLeft = '10px';
  mBtn.style.cursor = 'pointer';
  mBtn.onmousedown = function() {
    this.style.cursor = 'move';
    _self._source = node;
    PIDTreeUtils.removeById(_self._iRoot, node.id);
    _self._createTable.call(_self, _self._iRoot, table);
  };
  td.appendChild(mBtn);

  td = tr.insertCell(-1);
  elm = document.createElement('input');
  elm.type = 'radio';
  elm.name = 'homepage';
  elm.checked = node.is_default == 1;
  elm.onclick = function() {
    node.is_default = (this.checked) ? 1 : 0;
    new RequestUtils()._custom('homepage', JSON.stringify(node), function(result, params) {
    }, {
      pos : DOMUtils.findPos(this)
    });
  };
  td.appendChild(elm);

  td = tr.insertCell(-1);
  elm = document.createElement('input');
  elm.type = 'checkbox';
  elm.checked = node.appear_in_menu == 1;
  elm.onclick = function() {
    node.appear_in_menu = (this.checked) ? 1 : 0;
    new RequestUtils()._write(JSON.stringify( [ {
      n : 'pz_menu',
      a : [ node ],
      r : []
    } ]), function(result, params) {
    }, {
      pos : DOMUtils.findPos(this)
    });
  };
  td.appendChild(elm);

  td = tr.insertCell(-1);
  td.style.paddingRight = '10px';
  elm = document.createElement('select');
  elm.style.marginRight = '10px';
  var tmps = PageType.array();
  for ( var i = 0, il = tmps.length; i < il; i++) {
    var tmp = tmps[i];
    var op = new Option(tmp);
    elm.options[elm.options.length] = op;
    if (tmp == node.type) {
      elm.selectedIndex = elm.options.length - 1;
    }
  }
  elm.onchange = function() {
    _self._setPageTypes.call(_self, node, this.options[this.selectedIndex].text, DOMUtils.findPos(this));
  };
  td.appendChild(elm);

  if (node.type == Constant.PAGE_TYPE_LINK_INTERNAL) {
    var result = Utils.findMenu(this._root, node.url);
    if (result) {
      td.appendChild(document.createTextNode(result.name));
    }

    elm = document.createElement('img');
    elm.style.marginLeft = '10px';
    elm.src = 'image/edit.png';
    elm.style.cursor = 'pointer';
    elm.onclick = function() {
      _self._internal.call(_self, node, DOMUtils.findPos(this), false);
    };
    td.appendChild(elm);
  } else if (node.type == Constant.PAGE_TYPE_LINK_EXTERNAL) {
    td.appendChild(document.createTextNode(node.url));

    elm = document.createElement('img');
    elm.src = 'image/edit.png';
    elm.style.marginLeft = '10px';
    elm.style.cursor = 'pointer';
    elm.onclick = function() {
      _self._external.call(_self, node, DOMUtils.findPos(this), false);
    };
    td.appendChild(elm);
  } else if (node.type == Constant.PAGE_TYPE_LINK_DEV) {
    td.appendChild(document.createTextNode(node.url));

    elm = document.createElement('img');
    elm.src = 'image/edit.png';
    elm.style.marginLeft = '10px';
    elm.style.cursor = 'pointer';
    elm.onclick = function() {
      _self._custom.call(_self, node, DOMUtils.findPos(this), false);
    };
    td.appendChild(elm);
  }

  for ( var i = 0, il = node.c.length; i < il; i++) {
    var tmp = node.c[i];
    ancNumArr.push(i + 1);
    this._createTableRow(tmp, table, ancNumArr);
    ancNumArr.pop();
  }
};

/**
 * 
 */
Html_Pages.prototype._display = function(node, container) {
  if (node.id != 0) {
    this._displayNode(node, container, []);
  } else {
    for ( var i = 0, il = node.c.length; i < il; i++) {
      this._displayNode(node.c[i], container, [ i + 1 ]);
    }
  }
};

Html_Pages.prototype._displayNode = function(node, container, ancNumArr) {
  var span, prefix = '';

  var div;
  div = document.createElement('div');
  div.style.padding = '5px 0';
  div.style.letterSpacing = '1px';

  if (ancNumArr.length > 0) {
    this._setAncestorNum(div, ancNumArr);
  }

  div.appendChild(document.createTextNode(node.name));
  div.appendChild(document.createTextNode(' (' + node.order + ')'));
  container.appendChild(div);

  for ( var i = 0, il = node.c.length; i < il; i++) {
    var tmp = node.c[i];
    ancNumArr.push(i + 1);
    this._displayNode(tmp, container, ancNumArr);
    ancNumArr.pop();
  }
};

Html_Pages.prototype._setAncestorNum = function(container, ancNumArr) {
  prefix = '(';
  for ( var i = 0, il = ancNumArr.length; i < il; i++) {
    var tmp = ancNumArr[i]
    prefix += tmp + ((i < il - 1) ? '-' : '');
  }
  prefix += ') ';

  span = document.createElement('span');
  span.style.color = '#000000';
  span.style.fontSize = '14px';
  span.style.fontWeight = 'bold';
  span.style.marginLeft = (ancNumArr.length - 1) * 25 + 'px'
  span.appendChild(document.createTextNode(prefix));
  container.appendChild(span);
};

Html_Pages.prototype._setPageTypes = function(page, type, pos) {
  page.type = type;
  page.url = '';

  if (type == Constant.PAGE_TYPE_LINK_INTERNAL) {
    this._typeInternal(page, pos)
  } else if (type == Constant.PAGE_TYPE_LINK_EXTERNAL) {
    this._typeExternal(page, pos)
  } else if (type == Constant.PAGE_TYPE_LINK_DEV) {
    this._typeCustom(page, pos)
  } else {
    new RequestUtils()._write(JSON.stringify( [ {
      n : 'pz_menu',
      a : [ page ],
      r : []
    } ]), function(result, params) {
      location.reload();
    }, {
      pos : pos
    });
  }
};

Html_Pages.prototype._typeInternal = function(page, pos) {
  var p, elm, div, _self = this;

  p = new ModulePopupBox();
  div = document.createElement('div');
  div.style.paddingTop = '10px';
  elm = document.createElement('select');
  Utils.createMenuSel(elm, this._root, 0, [ page ], null);
  elm.onchange = function() {
    page.url = this.options[this.selectedIndex]._n.id;
    new RequestUtils()._write(JSON.stringify( [ {
      n : 'pz_menu',
      a : [ page ],
      r : []
    } ]), function(result, params) {
      location.reload();
    }, {
      pos : pos
    });
  };
  div.appendChild(elm);
  p._open(div, {
    pos : pos,
    width : 300,
    height : 90,
    t : 'Select a Internal Page'
  });
};

Html_Pages.prototype._typeExternal = function(page, pos) {
  var p, elm, table, tr, td, _self = this;

  page.url = (page.url == '') ? 'http://' : page.url;

  p = new ModulePopupBox();
  table = document.createElement('table');
  table.width = '100%';
  table.height = '100%';
  tr = table.insertRow(-1);
  td = tr.insertCell(-1);
  td.style.padding = '10px 10px';

  elm = document.createElement('input');
  elm.type = 'text';
  elm.value = page.url;
  elm.style.width = '100%';
  elm.onchange = function() {
    page.url = this.value;
  };
  td.appendChild(elm);

  tr = table.insertRow(-1);
  td = tr.insertCell(-1);
  td.style.textAlign = 'center';
  elm = document.createElement('input');
  elm.type = 'button';
  elm.value = 'OK';
  elm.style.width = '60px';
  elm.onclick = function() {
    new RequestUtils()._write(JSON.stringify( [ {
      n : 'pz_menu',
      a : [ page ],
      r : []
    } ]), function(result, params) {
      location.reload();
    }, {
      pos : pos
    });
  };
  td.appendChild(elm);
  elm = document.createElement('input');
  elm.type = 'button';
  elm.value = 'Cancel';
  elm.style.width = '60px';
  elm.onclick = function() {
    location.reload();
  };
  td.appendChild(elm);
  p._open(table, {
    pos : pos,
    width : 400,
    height : 150,
    t : '{{t escape='javascript'}}Enter a URL{{/t}}'
  });
};

Html_Pages.prototype._typeCustom = function(page, pos) {
  var p, elm, table, tr, td, _self = this;

  p = new ModulePopupBox();
  table = document.createElement('table');
  table.width = '100%';
  table.height = '100%';
  tr = table.insertRow(-1);
  td = tr.insertCell(-1);
  td.style.padding = '10px 10px';

  elm = document.createElement('input');
  elm.type = 'text';
  elm.value = page.url;
  elm.style.width = '100%';
  elm.onchange = function() {
    page.url = this.value;
  };
  td.appendChild(elm);

  tr = table.insertRow(-1);
  td = tr.insertCell(-1);
  td.style.textAlign = 'center';
  elm = document.createElement('input');
  elm.type = 'button';
  elm.value = 'OK';
  elm.style.width = '60px';
  elm.onclick = function() {
    new RequestUtils()._write(JSON.stringify( [ {
      n : 'pz_menu',
      a : [ page ],
      r : []
    } ]), function(result, params) {
      location.reload();
    }, {
      pos : pos
    });
  };
  td.appendChild(elm);
  elm = document.createElement('input');
  elm.type = 'button';
  elm.value = 'Cancel';
  elm.style.width = '60px';
  elm.onclick = function() {
    location.reload();
  };
  td.appendChild(elm);
  p._open(table, {
    pos : pos,
    width : 400,
    height : 150,
    t : '{{t escape='javascript'}}Enter a Template Name{{/t}}'
  });
};
